<template>
    <p>
        <ElSpace>
            <ElButton :loading="loading" type="primary" @click="getAll">刷新</ElButton>
            <ElButton type="success" @click="roles = {}; dfRef.show()">添加</ElButton>
        </ElSpace>
    </p>
    <Table :cols="cols" :data="list">
        <template #action="{ row }">
            <ElButton type="primary" @click="roles = { ...row }; dfRef.show();">修改</ElButton>
            <ElButton type="success" @click="openRightsDialog({ ...row })">设置权限</ElButton>
            <ElButton type="danger" @click="del(row)">删除</ElButton>
        </template>
    </Table>
    <DF labelWidth="80px" :title="roles.id ? '修改角色' : '添加角色'" :model="roles" :options="options" @ok="ok" ref="dfRef" />
    <Dialog title="权限设置" ref="dialogRef" @ok="confirmRights">
        <ElTree @check="checkChange" v-loading="rightsLoading" node-key="id" :default-checked-keys="checkedKeys"
            :data="menus" :props="{ label: 'name', children: 'children' }" show-checkbox />
    </Dialog>
</template>

<script lang="ts" setup>
import { ref } from 'vue';
import { getList, add, update, deleteRoles, IRoles, setRights } from '@/api/roles';
import { getAll as allMenus, IMenu, getRights } from '@/api/menus';
import confirm from '@/components/Confirm';
import { ElMessageBox } from 'element-plus';
import store from '@/store';

/**
 * 角色列表
 */
const list = ref<IRoles[]>([]);
/**
 * loading
 */
const loading = ref(false);
/**
 * 角色信息
 */
const roles = ref(<IRoles>{});
/**
 * dialog引用
 */
const dialogRef = ref();
/**
 * fd引用
 */
const dfRef = ref();
/**
 * 菜单列表
 */
const menus = ref<IMenu[]>([]);
/**
 * 默认选中的数据
 */
const checkedKeys = ref<number[]>([]);
/**
 * 权限loading
 */
const rightsLoading = ref(false);
/**
 * table列
 */
const cols = {
    name: {
        title: '角色名称'
    },
    description: {
        title: '描述'
    },
    action: {
        title: '操作',
        width: 260
    }
}
/**
 * 表单配置项
 */
const options = {
    name: {
        title: '角色名称',
        required: true,
        max: 20,
    },
    description: {
        title: '描述',
        required: true,
        max: 100,
    }
}

/**
 * 确定方法
 */
const ok = async (roles: IRoles) => {
    try {
        dfRef.value.start();
        await (roles.id ? update : add)(roles);
        getAll();
        dfRef.value.hide();
    } catch (error) { }
    dfRef.value.stop();
}

/**
 * 获取角色列表
 */
const getAll = async () => {
    try {
        loading.value = true;
        const data = await getList();
        list.value = data;
    } catch (error) { }
    loading.value = false;
}

/**
 * 删除
 * @param roles 
 */
const del = async ({ id, name }: IRoles) => {
    let res: any;
    try {
        res = await confirm(`您确定要删除【${name}】吗？`);
        await deleteRoles(id);
        getAll();
    } catch (error) { }
    res && res();
}

/**
 * 打开权限设置窗体
 */
const openRightsDialog = async (role: IRoles) => {
    try {
        if (store.state.user.role_id === role.id) {
            await ElMessageBox.confirm('要设置权限的角色跟当前登录用户角色一致，保存后需重新登录');
        }
        roles.value = role;
        dialogRef.value.show();
        rightsLoading.value = true;
        const [list, ids] = await Promise.all([allMenus(), getRights(role.id)]);
        checkedKeys.value = ids;
        /**
         * 找子菜单
         * @param parents 
         */
        const findChildren = (parents: IMenu[]) => {
            for (const parent of parents) {
                const children = list.filter(c => c.pid === parent.id);
                if (children.length) {
                    parent.children = children;
                    findChildren(children);
                }
            }
        }
        const top = list.filter(c => c.pid === 0);
        findChildren(top);
        menus.value = top;
    } catch (error) { }
    rightsLoading.value = false;
}

/**
 * check状态更改
 * @param data 
 * @param obj 
 */
const checkChange = (data: any, { checkedKeys: keys }: any) => {
    checkedKeys.value = keys;
}

/**
 * 提交权限设置
 */
const confirmRights = async () => {
    try {
        dialogRef.value.start();
        await setRights(roles.value.id, checkedKeys.value);
        dialogRef.value.hide();
        if (store.state.user.role_id === roles.value.id) {
            return store.dispatch('exit');
        }
    } catch (error) { }
    dialogRef.value.stop();
}

getAll();
</script>

<style></style>